#pragma once
#include "Cond.hpp"
#include "Mutex.hpp"
#include <iostream>
#include <queue>
#include <pthread.h>
namespace BlockQueueMuddle
{

    // v2
    using namespace MutexMoudle;
    using namespace CondMoudle;
    template <class T>
    class BlockQueue
    {
    private:
        bool isFull()
        {
            return _q.size() == _cap;
        }
        bool isEmpty()
        {
            return _q.empty();
        }

    public:
        BlockQueue(int cap) : _cap(cap), cwait_num(0), pwait_num(0)
        {
        }
        void Equeue(const T &in)
        {
            _mutex.Lock();
            while (isFull())
            {
                pwait_num++;
                _productor_cond.Wait(_mutex);
                std::cout << "生产者醒来！" << std::endl;
                pwait_num--;
            }
            _q.push(in);
            if (cwait_num)
            {
                _consumer_cond.Nodify();
            }
            _mutex.Unlock();
        }
        void Pop(T *out)
        {
            _mutex.Lock();
            while (isEmpty())
            {
                cwait_num++;
                _consumer_cond.Wait(_mutex);
                std::cout << "消费者醒来！" << std::endl;
                cwait_num--;
            }
            *out = _q.front();
            _q.pop();
            if (pwait_num)
            {
                _productor_cond.Nodify();
            }
            _mutex.Unlock();
        }
        ~BlockQueue()
        {
        }

    private:
        std::queue<T> _q;
        int _cap;     // bq最大容量
        Mutex _mutex; // 互斥
        Cond _productor_cond;
        Cond _consumer_cond;

        int cwait_num;
        int pwait_num;
    };
    // v1
    //  template <class T>
    //  class BlockQueue
    //  {
    //  private:
    //      bool isFull()
    //      {
    //          return _q.size() == _cap;
    //      }
    //      bool isEmpty()
    //      {
    //          return _q.empty();
    //      }

    // public:
    //     BlockQueue(int cap) : _cap(cap), cwait_num(0), pwait_num(0)
    //     {
    //         pthread_mutex_init(&_mutex,nullptr);
    //         pthread_cond_init(&_productor_cond,nullptr);
    //         pthread_cond_init(&_consumer_cond,nullptr);
    //     }
    //     void Equeue(const T &in)
    //     {
    //         pthread_mutex_lock(&_mutex);
    //         while (isFull())
    //         {
    //             pwait_num++;
    //             pthread_cond_wait(&_productor_cond, &_mutex);
    //             std::cout<<"生产者醒来！"<<std::endl;
    //             pwait_num--;
    //         }
    //         _q.push(in);
    //         if (cwait_num)
    //         {
    //             pthread_cond_signal(&_consumer_cond);
    //         }
    //         pthread_mutex_unlock(&_mutex);
    //     }
    //     void Pop(T*out)
    //     {
    //         pthread_mutex_lock(&_mutex);
    //         while (isEmpty())
    //         {
    //             cwait_num++;
    //             pthread_cond_wait(&_consumer_cond, &_mutex);
    //             std::cout<<"消费者醒来！"<<std::endl;
    //             cwait_num--;
    //         }
    //         *out=_q.front();
    //         _q.pop();
    //         if (pwait_num)
    //         {
    //             pthread_cond_signal(&_productor_cond);
    //         }
    //         pthread_mutex_unlock(&_mutex);
    //     }
    //     ~BlockQueue()
    //     {
    //         pthread_mutex_destroy(&_mutex);
    //         pthread_cond_destroy(&_productor_cond);
    //         pthread_cond_destroy(&_consumer_cond);
    //     }

    // private:
    //     std::queue<T> _q;
    //     int _cap;               // bq最大容量
    //     pthread_mutex_t _mutex; // 互斥
    //     pthread_cond_t _productor_cond;
    //     pthread_cond_t _consumer_cond;

    //     int cwait_num;
    //     int pwait_num;
    // };
}